package com.pic.mgt.monitor.physicalmonitor;

import java.io.FilenameFilter;
import java.util.List;

/**
 * [檔案監控界面]
 * 用以提供檔案監控機制，目前只支援監控單一目錄。
 * 監控某特定目錄下檔案的產生.刪除.修改。 
 * @author 洪政緯  
 */
public interface FileMonitor {
	/**
	 * [檔案監控事件]
	 * 監控事件:FILE_Generate,EVENTOVERFLOW,FILE_CREATE,FILE_DELETE,FILE_MOTIFY；
	 * 以下僅支援Linux 平台並使用支援 Inotify 實作使用: FILE_CLOSING, FILE_CLOSE_NO_WRITE,
	 *  FILE_CLOSE_WRITE, FILE_OPEN。
	 * @author 洪政緯
	 */
	public static enum FileMonitorEvent {
		FILE_Generate, // 泛指檔案被產生出來的事件(由實作根據本身所提供的事件，自行做對應)
		EVENTOVERFLOW, // Overflow 表示檔案的監控有遺失的情況發生
		FILE_CREATE,
		FILE_DELETE,
		FILE_MOTIFY,
		// === 以下僅支援 Linux ===
		FILE_CLOSING, // 檔案正在關閉
		FILE_CLOSE_NO_WRITE, // 檔案關閉(不是因為要寫入檔案而被打開的)
		FILE_CLOSE_WRITE, //檔案關閉(是因為要寫入檔案而被打開的)
		FILE_OPEN
		};
	
		/**
		 * 檔案監控狀態
		 * @author 洪政緯
		 */
	public static enum FileMonitorStatus {
		MONITOR_INITIAL, MONITOR_STOPPED, MONITOR_STARTED
	}
	
	/**
	 * 新增監控目錄於清單中。若監控狀態為已開始(MONITOR_STARTED)的情況下，則會一併直接開始進行監控。
	 * @param monitorPath
	 * @throws FileMonitorStopException
	 */
	public void addMonitorPath(String monitorPath) throws FileMonitorException;
	
	/**
	 * 移除並停止監控所有的檔案監控路徑
	 * 如果監控狀態為 MONITOR_STARTED 則呼叫此方法不會有作用
	 */
	public void removeAllMonitorPath();
	
	/**
	 * 移除並停止監控所指定的檔案監控路徑
	 * @param monitorPath
	 */
	public void removeMonitorPath(String monitorPath);
	
	/**
	 * 針對讓某一個目錄停止監控。呼叫本方法前是所監控的目錄，已經先行
	 * 新增 (addMonitorPath(String))於清單中，並且監控狀態是在開始(MONITOR_STARTED)的情況下才會生效。
	 * @param monitorPathStr
	 */
	public void stopWatchMonitorPath(String monitorPathStr);
	
	/**
	 * 停止所有目錄的監控，但不從清單中移除。
	 */
	public void stopWatchAllMonitorPath();
	
	/**
	 * 設定監控事件。
	 * 如果監控狀態為 MONITOR_STARTED 則呼叫此方法不會有作用
	 * @param monitorEvents
	 */
	public void setMonitorEvent(FileMonitorEvent ... monitorEvents);
	
	/**
	 * 開始監控所有位於清單中的目錄。
	 * @param eventListener
	 * @throws FileMonitorException 
	 * 				 發生 FileMonitorException 有二種情況:
	 * 				(1) 在建立底層檔案監控元件時發生的錯誤，此時完全無法監控(監控狀態也不會是在 running 的狀態)。
	 * 				(2) 建立底層檔案監控元件成功，但在加入目錄監控時發生錯誤(有可能是目錄不存在或其它狀況等)，此
	 * 					時要注意的是監控狀態會是在 running ，並且先前有加入目錄監控成功的目錄應是正常在監控的。
	 */
	public void startMonitor() throws FileMonitorException;
	
	/**
	 * 如果有呼叫 stopWatchMonitorPath(String) 方法來針對讓某一個目錄停止監控，
	 * 則可以呼叫此方法，同樣針對該目錄繼續開始監控。呼叫本方法前是所監控的目錄，已經先行
	 * 新增 (addMonitorPath(String))於清單中，並且監控狀態是在開始(MONITOR_STARTED)的情況下才會生效。
	 * @param monitorPathStr
	 * @throws FileMonitorException
	 */
	public void startWatchMonitorPath(String monitorPathStr) throws FileMonitorException;
	
	/**
	 * 停止所有的目錄監控。
	 */
	public void stopMonitor();
	
	/**
	 * 讀取監控到的檔案變動清單。
	 * 若內容為空，呼叫此方法會等待，一直到有資料時才回傳。
	 * 若回傳的List內容為空，可能的原因，是因為設定了過濾器。
	 * 對於 List 內的資料(MonitoredFile)，若其中的 ChangedEvent 為 OVERFLOW，
	 * 則 ChangedFile 會為 Null。
	 * @return 不會為 Null。
	 */
	public List<MonitoredFile> readMonitoredList() throws FileMonitorStopException;
	
	/**
	 * 設定檔名過濾器。
	 * Filename Filter 不能夠在 Monitor Status 為 Started 情況下改變
	 * @param filenameFilter
	 */
	public void addFilenameFilter(FilenameFilter filenameFilter);
	
	/**
	 * 移除檔名過濾器。
	 * Filename Filter 不能夠在 Monitor Status 為 Started 情況下改變
	 */
	public void removeAllFilenameFilter();
	
	public FileMonitorStatus getMonitorStatus();
}
